﻿using NLog;
using PagedList.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using Wabo.Dal;
using Wabo.Dal.Interface;
using Wabo.Dal.Repository;
using Wabo.Web.Areas.Manager.Models;
using Wabo.Web.Areas.Manager.ViewModels;
using Wabo.Web.Resources;

namespace Wabo.Web.Areas.Manager.Core
{
    /// <summary>
    /// Base class for all controllers in project.
    /// + Enables controllers to access base modules ( Module,User,Group )
    /// + Enables controllers to log events
    /// + Prepares admin menu items based on current user's permissons
    /// </summary>
    public class WaboController : Controller
    {        

        protected IModuleRepository ModuleContext = new WaboEFModuleRepository();
        protected IUserRepository UserContext = new WaboEFUserRepository();
        protected IGroupRepository GroupContext = new WaboEFGroupRepository();
        protected ISystemSettingsRepository SystemSettingsContext = new WaboEFSystemSettingsRepository();
        protected IMessageRepository UserMessages = new WaboEFMessageRepository();
        protected ILocks LockContext = new WaboEFLockRepository();
        
        private ILogRepository LogContext = new WaboEFLogRepository();        
        private WaboSystemMenuViewModel AdminMenu = new WaboSystemMenuViewModel();

        private StringBuilder InfoMessage = new StringBuilder();

        private const string ACTION_HAS_MESSAGE_TOKEN = "ControllerActionHasMessageToShare";


        public void AddActionMessageToken(object obj)
        {
            SessionManager.RegisterSessionObject(ACTION_HAS_MESSAGE_TOKEN, obj);                
        }
        public object GetActionMessageToken()
        {
            return SessionManager.ReturnSessionObject(ACTION_HAS_MESSAGE_TOKEN);
        }
        public void ClearActionMessageToken()
        {
            SessionManager.FreeSessionObject(ACTION_HAS_MESSAGE_TOKEN);
        }

        public void AddInfoMessage(string msg)
        {
            InfoMessage.AppendLine(msg);
        }
        
        
        /// <summary>
        /// Return current logged in user. Added just not to use SessionManager everytime 
        /// </summary>
        public Dal.User AuthorizedUser 
        { 
            get
            {
                return SessionManager.AuthorizedUser();
            } 
        }

        public WaboController()
        {
            // If we have a logged in user, build modules menu
            if (AuthorizedUser != null)
            {
                foreach (Module m in ModuleContext.Modules.OrderBy(m => m.order))
                {
                    
                    if (m.show_on_menu && ModuleContext.UserCanList(AuthorizedUser, m))
                        AdminMenu.Menu.Add(new WaboSystemMenuItem {Title = m.title, ControllerName = m.controller});
                }
            }
        }
        
        protected override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            var activeControllerName = ControllerContext.Controller.GetType().Name.Replace("Controller", "");
            foreach (var menuItem in AdminMenu.Menu)
            {
                menuItem.Selected = menuItem.ControllerName == activeControllerName;
            }
            // Pass System Settings
            ViewBag.SystemSettings = SystemSettingsContext.Settings;
            // Set Current Application Name
            ViewBag.ApplicationName = SystemSettingsContext.ApplicationName;
            // Set path to current theme
            ViewBag.ThemePath = WaboViewEngine.ThemesBasePath+SystemSettingsContext.Theme+"/";
            // Add current user information and menu items containing module information 
            // to build top menu bar 
            ViewBag.AdminMenu = AdminMenu;
            ViewBag.ActiveUser = AuthorizedUser;
            // Prepare paged list render options
            ViewBag.PagerRenderOptions = new PagedListRenderOptions();
            ViewBag.PagerRenderOptions.ItemSliceAndTotalFormat = Messages.PagedListItemSliceAndTotalFormat;
            ViewBag.PagerRenderOptions.DisplayItemSliceAndTotal = true;
            // Get unread message count            
            try
            {
                var unreadMessages = UserMessages.GetUnreadRootMessagesOfUser(AuthorizedUser);
                ViewBag.UnreadMessageCount = unreadMessages.Count();
            }
            catch (System.Reflection.TargetException ex)
            {
                ViewBag.UnreadMessageCount = 0;
            }
            catch (ArgumentNullException ex)
            {
                ViewBag.UnreadMessageCount = 0;
            }            
            // Set info messages
            ViewBag.InfoMessage = InfoMessage.ToString();
            InfoMessage.Clear();

            base.OnResultExecuting(filterContext);
        }
        /// <summary>
        /// Writes exception information to current NLog target. Mostly a file
        /// </summary>
        /// <param name="errorMessage"></param>
        protected void LogError(string errorMessage)
        {
            var moduleName = ControllerContext.Controller.GetType().Name.Replace("Controller", "");            
            var logger = LogManager.GetLogger(moduleName);
            logger.Error(errorMessage);
        }

        /// <summary>
        /// Write event information to log table
        /// </summary>        
        /// <param name="operation">Operation Type</param>
        /// <param name="description">Optional information about the event</param>
        protected void LogEvent( LogOperation operation, string description = "")
        {
            string moduleName = ControllerContext.Controller.GetType().Name.Replace("Controller", "");
            string actionName = ControllerContext.RouteData.Values["action"].ToString();
            LogContext.Log(AuthorizedUser, operation, moduleName, actionName,description);
        }

        protected void PurgeLogs(int days)
        {
            LogContext.Remove(days);
        }
        protected IQueryable<WaboLog> EventLogs()
        {
            return LogContext.Logs;
        }
        // ---------------------------------------------------------------------------------
        // Helper methods for the lazy one ( me )
        // ---------------------------------------------------------------------------------
        protected object FindCookie(string cookieName)
        {
            try
            {
                HttpCookie cookie = ControllerContext.HttpContext.Request.Cookies["WABO_Cookies"];
                if (cookie != null)
                    return cookie.Values[cookieName];
                return null;
            }
            catch (Exception ex)
            {
                LogError(ex.Message);
            }
            return null;
        }
        // ---------------------------------------------------------------------------------
        protected void AddCookie(string cookieName, string cookieData, int secondsToExpire = 604800)
        {
            try
            {
                var cookie = new HttpCookie("WABO_Cookies")
                    {
                        Expires = DateTime.Now.AddSeconds(secondsToExpire)
                    };

                cookie.Values.Add(cookieName, cookieData);
                ControllerContext.HttpContext.Response.Cookies.Add(cookie);
            }
            catch (Exception ex)
            {
                LogError(ex.Message);
            }
        }
        // ---------------------------------------------------------------------------------
        protected void ClearCookie(string cookieName)
        {
            AddCookie(cookieName,"",-604800);
        }
        

        

    }
}
